package finalproject.mobapp.ARPackage;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import finalproject.mobapp.R;
import finalproject.mobapp.Main.ARViewActivity;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.location.Location;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class ARView extends View{
	static final float gamma_h = 90;
	static final float gamma_v = 50;
	
	public ARViewActivity act;
	public Location myLocation;
	public Location poiLocation;
	public HashMap<Integer, Poi> nearbyPois;
	public boolean isTakeMeThere = false;
	
	public HashMap<Integer, Float[]> poiPositions;
	public HashMap<Integer, Float[]> poiTouchArea;
	public HashMap<Integer, Float[]> objectTouchArea;
	
	private Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
	private boolean firstDraw;
	private boolean isOnTouch;
	private int poiTouchedId = 0;
	
	public ARView(Context context) {
		super(context);
		init();
	}
	
	public ARView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}
	
	public ARView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}
	
	public ARView(Context context, ARViewActivity _act) {
		super(context);
		act = _act;
		init();
	}
	
	private void init() {
		textPaint.setStyle(Paint.Style.STROKE);
		textPaint.setColor(Color.WHITE);
		
		firstDraw = true;
		isOnTouch = false;
	}
	
	public void setMyLocation(Location _myLocation) {
		myLocation = _myLocation;
	}
	
	public void setPoiPositions(HashMap<Integer, Float[]> _poiPositions) {
		poiPositions = _poiPositions;
	}
	
	public void setNearbyPois(HashMap<Integer, Poi> _nearbyPois) {
		nearbyPois = _nearbyPois;
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
	}

	@Override
	protected void onDraw(Canvas canvas) {
		float halfWidth = (float) (getMeasuredWidth() * 0.5);
		float halfHeight = (float) (getMeasuredHeight() * 0.5);
		
		if(!firstDraw){
			if (isOnTouch) {
				Poi poi = nearbyPois.get(poiTouchedId);
				
				objectTouchArea = new HashMap<Integer, Float[]>();
				int id = -3;
				
				//draw AR object of selected poi
				Float[] values = poiPositions.get(poiTouchedId);
				float betha = values[0];
				float pitch = values[1];
				
				if (Math.abs(betha)<gamma_h/2/* && Math.abs(pitch+90)<gamma_v/2*/) {
					if (pitch<0 && pitch>-180) {
						Bitmap icon_pic = BitmapFactory.decodeResource(getResources(), R.drawable.poi_icon);
						int icon_width = icon_pic.getWidth();
						int icon_height = icon_pic.getHeight();
						
						float y_init = halfHeight * (4000 - poi.getDistance()) / 3000;
						float dy = (-1) * halfHeight * (pitch + 90) / 90;
						float y_draw = y_init + dy;
						
						//float dx = (float) (halfHeight * Math.tan((double)(betha) * 3.14 / 180));
						float dx = (float) ((getMeasuredHeight()-y_draw) * Math.tan((double)(betha) * 3.14 / 180));
						float x_draw = halfWidth + dx;
						
						id++;
						Float[] touchAreaIcon = {x_draw, y_draw, (float)(x_draw+icon_width), (float)(y_draw+icon_height)};
						objectTouchArea.put(id, touchAreaIcon);
						
						canvas.drawBitmap(icon_pic, x_draw, y_draw, null);
						canvas.drawText(poi.getTitle(), x_draw, y_draw, textPaint);
						
						Bitmap mapbtn_pic = BitmapFactory.decodeResource(getResources(), R.drawable.map_btn);
						float x_mapbtn = x_draw;
						float y_mapbtn = (float)(y_draw + icon_height + 5);
						canvas.drawBitmap(mapbtn_pic, x_mapbtn, y_mapbtn, null);
						
						id++;
						Float[] touchAreaMap = {x_mapbtn, y_mapbtn, (float)(x_mapbtn+mapbtn_pic.getWidth()), (float)(y_mapbtn+mapbtn_pic.getHeight())};
						objectTouchArea.put(id, touchAreaMap);
						
						Bitmap infobtn_pic = BitmapFactory.decodeResource(getResources(), R.drawable.info_btn);
						float x_infobtn = x_draw;
						float y_infobtn = (float) (y_mapbtn + mapbtn_pic.getHeight() + 5);
						canvas.drawBitmap(infobtn_pic, x_infobtn, y_infobtn, null);
						
						id++;
						Float[] touchAreaInfo = {x_infobtn, y_infobtn, (float)(x_infobtn+infobtn_pic.getWidth()), (float)(y_infobtn+infobtn_pic.getHeight())};
						objectTouchArea.put(id, touchAreaInfo);
						
						/** processing object **/
						ArrayList<ARObject> objects = poi.getObjects();
						if (objects.size() == 1) {
							ARObject object = objects.get(0);
							Bitmap objectIcon = null;
							if (object.getType() == 1) {
								//type image
								objectIcon = BitmapFactory.decodeResource(getResources(), R.drawable.image_btn);
							} else if (object.getType() == 2) {
								//type video
								objectIcon = BitmapFactory.decodeResource(getResources(), R.drawable.video_btn);
							}
							int objecticon_width = objectIcon.getWidth();
							int objecticon_height = objectIcon.getHeight();

							float x_drawobjecticon = x_draw - 5 - objecticon_width;
							float y_drawobjecticon = y_draw;

							canvas.drawBitmap(objectIcon, x_drawobjecticon, y_drawobjecticon, null);

							Float[] touchAreaObject = {x_drawobjecticon, y_drawobjecticon, (float)(x_drawobjecticon+objecticon_width), (float)(y_drawobjecticon+objecticon_height)};
							objectTouchArea.put(object.getId(), touchAreaObject);
						} else if (objects.size() == 2) {
							for (int i=0; i<objects.size(); i++) {
								ARObject object = objects.get(i);
								Bitmap objectIcon = null;
								if (object.getType() == 1) {
									//type image
									objectIcon = BitmapFactory.decodeResource(getResources(), R.drawable.image_btn);
								} else if (object.getType() == 2) {
									//type video
									objectIcon = BitmapFactory.decodeResource(getResources(), R.drawable.video_btn);
								}
								int objecticon_width = objectIcon.getWidth();
								int objecticon_height = objectIcon.getHeight();

								float x_drawobjecticon = 0;
								float y_drawobjecticon = y_draw;
								if (i==0) {
									x_drawobjecticon = x_draw - 5 - objecticon_width;
								} else if (i==1) {
									x_drawobjecticon = x_draw + 5 + icon_width;
								}

								canvas.drawBitmap(objectIcon, x_drawobjecticon, y_drawobjecticon, null);

								Float[] touchAreaObject = {x_drawobjecticon, y_drawobjecticon, (float)(x_drawobjecticon+objecticon_width), (float)(y_drawobjecticon+objecticon_height)};
								objectTouchArea.put(object.getId(), touchAreaObject);
							}
						}
						/** end of processing object **/
					}
				}
			} else {
				//draw all pois
				poiTouchArea = new HashMap<Integer, Float[]>();
				Iterator<Integer> e = poiPositions.keySet().iterator();
				do {
					int poi_id = e.next();
					Poi poi = nearbyPois.get(poi_id);
					Float[] values = poiPositions.get(poi_id);
					float betha = values[0];
					float pitch = values[1];
					
					if (Math.abs(betha)<gamma_h/2/* && Math.abs(pitch+90)<gamma_v/2*/) {
						if (pitch<0 && pitch>-180) {
							Bitmap pic = BitmapFactory.decodeResource(getResources(), R.drawable.poi_icon);
							int pic_width = pic.getWidth();
							int pic_height = pic.getHeight();
							
							float y_init = halfHeight * (4000 - poi.getDistance()) / 3000;
							float dy = (-1) * halfHeight * (pitch + 90) / 90;
							float y_draw = y_init + dy;
							
							//float dx = (float) (halfHeight * Math.tan((double)(betha) * 3.14 / 180));
							float dx = (float) ((getMeasuredHeight()-y_draw) * Math.tan((double)(betha) * 3.14 / 180));
							float x_draw = halfWidth + dx;
							
							Float[] touchArea = {x_draw, y_draw, (float)(x_draw+pic_width), (float)(y_draw+pic_height)};
							poiTouchArea.put(poi_id, touchArea);
							
							canvas.drawBitmap(pic, x_draw, y_draw, null);
							canvas.drawText(poi.getTitle(), x_draw, y_draw, textPaint);
						}
					}
					
				} while (e.hasNext());
			}
		}
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		final int action = ev.getAction();
		
		if (isOnTouch) {
			switch (action & MotionEvent.ACTION_MASK) {
			case MotionEvent.ACTION_DOWN:
				float xPos = ev.getX();
				float yPos = ev.getY();
				
				//cari x_touch dan y_touch di poiTouchArea
				//kalo ketemu, draw AR object
				//kalo gak ketemu, do nothing
				int object_id = searchObjectTouch(xPos, yPos);
				if (object_id == -3) {
					//salah, gak ketemu, do nothing
				} else {
					if (object_id == -2) {
						//ikon POI yg disentuh
						isOnTouch = false;
						invalidate();
					} else if (object_id == -1) {
						//ikon map yg disentuh
						act.takeMeThere(poiTouchedId);
					} else if (object_id == 0) {
						//ikon info yg disentuh
						act.viewInfo(poiTouchedId);
					}else if (object_id > 0){
						//aksi sesuai id dari object yg disentuh
						act.ARObjectHandle(poiTouchedId, object_id);
						//isOnTouch = false;
						//invalidate();
					}
				}
				break;

			default:
				break;
			}
		} else {
			switch (action & MotionEvent.ACTION_MASK) {
			case MotionEvent.ACTION_DOWN:
				float xPos = ev.getX();
				float yPos = ev.getY();
				
				//cari x_touch dan y_touch di poiTouchArea
				//kalo ketemu, draw AR object
				//kalo gak ketemu, do nothing
				int poi_id = searchPointTouch(xPos, yPos);
				if (poi_id == 0) {
					//salah, gak ketemu, do nothing
				} else {
					drawAR(poi_id);
				}
				break;

			default:
				break;
			}
		}
		return true;
	}
	
	public void drawAR(int poi_id) {
		isOnTouch = true;
		poiTouchedId = poi_id;
		invalidate();
	}
	
	public int searchObjectTouch(float xPos, float yPos) {
		int retval = -3;
		
		boolean found = false;
		
		if (objectTouchArea.size() > 0) {
			//lakukan pencarian
			Iterator<Integer> e = objectTouchArea.keySet().iterator();
			do {
				int object_id = e.next();
				Float[] areaTouch = objectTouchArea.get(object_id);
				float x_min = areaTouch[0];
				float y_min = areaTouch[1];
				float x_max = areaTouch[2];
				float y_max = areaTouch[3];
				
				if (xPos>=x_min && xPos<=x_max && yPos>=y_min && yPos<=y_max) {
					found = true;
					retval = object_id;
				}
			} while (!found && e.hasNext());
		}
		
		return retval;
	}
	
	public int searchPointTouch(float xPos, float yPos) {
		int retval = 0;
		boolean found = false;
		
		if (poiTouchArea.size() > 0) {
			//lakukan pencarian
			Iterator<Integer> e = poiTouchArea.keySet().iterator();
			do {
				int poi_id = e.next();
				Float[] areaTouch = poiTouchArea.get(poi_id);
				float x_min = areaTouch[0];
				float y_min = areaTouch[1];
				float x_max = areaTouch[2];
				float y_max = areaTouch[3];
				
				if (xPos>=x_min && xPos<=x_max && yPos>=y_min && yPos<=y_max) {
					found = true;
					retval = poi_id;
				}
			} while (!found && e.hasNext());
		}
		
		return retval;
	}
	
	public void updateLayout(HashMap<Integer, Float[]> _poiPositions) {
		firstDraw = false;
		setPoiPositions(_poiPositions);
		invalidate();
	}
}
